package com.cndw.kungfu.model.activity.domain;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import com.cndw.kungfu.config.ConstantsConfig;
import com.cndw.kungfu.config.ConstantsRadio;
import com.cndw.kungfu.domain.Monster;
import com.cndw.kungfu.domain.MonsterDeploy;
import com.cndw.kungfu.domain.Player;
import com.cndw.kungfu.domain.Scene;
import com.cndw.kungfu.event.model.WorldBossHandler;
import com.cndw.kungfu.ext.LangUtil;
import com.cndw.kungfu.ext.LanguageLib;
import com.cndw.kungfu.ext.LogUtil;
import com.cndw.kungfu.ext.TimeProcesser;
import com.cndw.kungfu.ext.XmlProcesser;
import com.cndw.kungfu.model.Context;
import com.cndw.kungfu.model.battle.FighterMonster;
import com.cndw.kungfu.model.goods.domain.SubPops;
import com.cndw.kungfu.model.goods.domain.SysModeAwards;
import com.cndw.kungfu.model.sys.ChatMain;
import com.cndw.kungfu.vo.EventNotice;
import com.cndw.kungfu.vo.WorldBossAkVo;

public class WorldBoos implements Comparable<WorldBoos> {
	private static Map<Integer, WorldBoos> commData = new HashMap<Integer, WorldBoos>();

	private static Map<Integer, WorldBoos> sceneData = new HashMap<Integer, WorldBoos>();

	public static final int bossLifeTime = 1800;
	/**
	 * 编号
	 */
	private int id;
	/**
	 * 怪物id
	 */
	private int monsterId;
	/**
	 * 怪物部署id
	 */
	private int monsterDeployId;
	/**
	 * 最低等级
	 */
	private int level;
	/**
	 * 最高等级
	 */
	private int levelMax;
	/**
	 * 第一次刷新时间
	 */
	private int refreshTime;
	/**
	 * 所在场景
	 */
	private int currentSceneId;
	/**
	 * 奖励编号
	 */
	private int awardsRootId;

	private int lastRefresh;
	/**
	 * boss对象
	 */
	private FighterMonster bossFighter;

	private int bossHpMax = 0;
	private int currntSmallAk = 0;
	/**
	 * 伤害血量
	 */
	private Map<Long, Integer> playerDaMap = new ConcurrentHashMap<Long, Integer>();
	private Map<Long, Integer> playerAkMap = new ConcurrentHashMap<Long, Integer>();
	/**
	 * buff属性量
	 */
	private Map<Long, Integer> playerBuffMap = new ConcurrentHashMap<Long, Integer>();
	/**
	 * 玩家死亡复活时间
	 */
	private Map<Long, Integer> playerDeadMap = new ConcurrentHashMap<Long, Integer>();

	private long lastBlowKiller;
	/**
	 * 上次击杀者
	 */
	private long lastKillerId;
	private String lastKillerName;
	private List<WorldBossAkVo> akList;
	private int lastClac;

	private static int bosslastDead = 0;

	static {
		load();
	}

	public static void load() {
		List<WorldBoos> tempList = XmlProcesser.processXml(WorldBoos.class, ConstantsConfig.getLocaleResource() + "worldBoos.xml");
		Map<Integer, WorldBoos> tempMap = new HashMap<Integer, WorldBoos>();
		for (WorldBoos e : tempList) {
			tempMap.put(e.getId(), e);
		}
		commData = tempMap;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getMonsterId() {
		return monsterId;
	}

	public void setMonsterId(int monsterId) {
		this.monsterId = monsterId;
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public int getLevelMax() {
		return levelMax;
	}

	public void setLevelMax(int levelMax) {
		this.levelMax = levelMax;
	}

	public int getRefreshTime() {
		return refreshTime;
	}

	public void setRefreshTime(int refreshTime) {
		this.refreshTime = refreshTime;
	}

	public int getAwardsRootId() {
		return awardsRootId;
	}

	public void setAwardsRootId(int awardsRootId) {
		this.awardsRootId = awardsRootId;
	}

	public int getMonsterDeployId() {
		return monsterDeployId;
	}

	public void setMonsterDeployId(int monsterDeployId) {
		this.monsterDeployId = monsterDeployId;
	}

	public FighterMonster getBossFighter() {
		return bossFighter;
	}

	public void setBossFighter(FighterMonster bossFighter) {
		this.bossFighter = bossFighter;
	}

	public int getBossHpMax() {
		return bossHpMax;
	}

	public boolean isFirst(long playerId) {
		return !playerDaMap.containsKey(playerId);
	}

	public void damIncrement(long playerId, int dam) {
		int times = 1;
		if (playerDaMap.containsKey(playerId)) {
			dam += playerDaMap.get(playerId);
			times += playerAkMap.get(playerId);
		}
		playerDaMap.put(playerId, dam);
		playerAkMap.put(playerId, times);
		if (dam >= currntSmallAk || playerAkMap.size() <= 10) {
			broadcastOrder(0);// 广播全线血量变化
		} else {
			broadcastHp();
		}
	}

	public int getAkTimes(long playerId) {
		if (!playerAkMap.containsKey(playerId)) {
			return 0;
		}
		return playerAkMap.get(playerId);
	}

	public int getDamById(long playerId) {
		if (!playerDaMap.containsKey(playerId)) {
			return 0;
		}
		return playerDaMap.get(playerId);
	}

	public void Refresh() {
		if (lastRefresh < TimeProcesser.getMorningTime() + refreshTime) {
			lastRefresh = TimeProcesser.getMorningTime() + refreshTime;
			playerDaMap.clear();
			playerAkMap.clear();
			playerDeadMap.clear();
			lastBlowKiller = 0;
			currntSmallAk = 0;
			bossHpMax = 0;

			Monster monster = Context.getUndercityServer().getMonster(monsterId);
			MonsterDeploy deploy = Context.getUndercityServer().getDeployById(monsterDeployId);
			if (monster != null) {
				bossFighter = monster.fighter();
				bossHpMax = bossFighter.getMaxHp();
			}
			currentSceneId = deploy.getSceneId();
			sceneData.put(currentSceneId, this);

			Scene scene = Context.getSceneServer().getSceneById(currentSceneId);
			// String message = LanguageLib.get("activity.boos.refresh",
			// monster.getName(), scene.getName());
			// ChatMain.systemMessage(message);

			if (deploy != null) {
				EventNotice notice = new EventNotice(ConstantsRadio.boss, ConstantsRadio.boss_Refresh);
				notice.comitData(deploy);
				notice.put("bossHpMax", bossHpMax);
				notice.put("bossHp", bossHpMax);
				notice.broadcast(scene.getPlayerIds(0));// 广播全线人
				LogUtil.getSystem().debug("broad refresh bossid:" + id);
			}

		}
	}

	public void checkDead(int constTime, long lastBlowKiller) {
		if (bossFighter != null && bossFighter.getHp() <= 0 && lastClac < lastRefresh) {
			synchronized (this) {
				if (bossFighter != null) {
					bossFighter = null;
					currntSmallAk = 0;
					this.lastBlowKiller = lastBlowKiller;
					bosslastDead = TimeProcesser.getUnixTime();
					Context.getTimerServer().scheduleSeconds(new WorldBossHandler(this, 1), constTime + 5);
				}
			}
		}
	}

	public synchronized void process() {
		if (lastClac < lastRefresh) {
			lastClac = TimeProcesser.getUnixTime();
			orderDam();
			if (bossFighter != null) {
				bossFighter = null;
				broadcastDead();
			}
		}

	}

	public void broadcastDead() {
		Scene scene = Context.getSceneServer().getSceneById(currentSceneId);
		if (scene != null) {
			EventNotice notice = new EventNotice(ConstantsRadio.boss, ConstantsRadio.boss_Dead);
			notice.put("bossId", monsterDeployId);
			// notice.broadcast(scene.getPlayerIds(0));//广播全线人
			notice.broadCastAllOnLine();
			LogUtil.getSystem().debug("broad dead bossid:" + id);
		}
	}

	public void broadcastOrder(long playerId) {
		EventNotice notice = new EventNotice(ConstantsRadio.boss, ConstantsRadio.boss_OrderList);
		notice.put("orderList", currentAkList());
		notice.put("bossHpMax", bossHpMax);
		notice.put("bossHp", bossFighter == null ? 0 : bossFighter.getHp());
		notice.put("akNums", playerAkMap.size());

		if (playerId > 0) {
			notice.broadcast(playerId);
		} else {
			Scene scene = Context.getSceneServer().getSceneById(currentSceneId);
			if (scene != null) {
				notice.broadcast(scene.getPlayerIds(0));
			}
		}
	}

	public void broadcastHp() {
		EventNotice notice = new EventNotice(ConstantsRadio.boss, ConstantsRadio.boss_OrderList);
		notice.put("bossHpMax", bossHpMax);
		notice.put("bossHp", bossFighter == null ? 0 : bossFighter.getHp());
		notice.put("akNums", playerAkMap.size());
		Scene scene = Context.getSceneServer().getSceneById(currentSceneId);
		if (scene != null) {
			notice.broadcast(scene.getPlayerIds(0));
		}
	}

	public List<WorldBossAkVo> currentAkList() {
		ArrayList<Entry<Long, Integer>> newList = gotList();
		List<WorldBossAkVo> orderList = new ArrayList<WorldBossAkVo>();
		int orderId = 0;
		for (Entry<Long, Integer> e : newList) {
			orderId++;
			long playerId = e.getKey();
			int akNum = playerAkMap.get(playerId);
			int damNum = playerDaMap.get(playerId);
			WorldBossAkVo akVo = new WorldBossAkVo(playerId, orderId, akNum, damNum);
			orderList.add(akVo);

			if (orderId == 10) {
				currntSmallAk = damNum;
			}
			if (orderId >= 10) {
				break;
			}
		}
		return orderList;
	}

	private ArrayList<Entry<Long, Integer>> gotList() {
		ArrayList<Entry<Long, Integer>> newList = new ArrayList<Entry<Long, Integer>>(playerDaMap.entrySet());

		Collections.sort(newList, new Comparator<Map.Entry<Long, Integer>>() {
			public int compare(Map.Entry<Long, Integer> o1, Map.Entry<Long, Integer> o2) {
				return (o2.getValue() - o1.getValue());
			}
		});
		return newList;
	}

	private void orderDam() {
		ArrayList<Entry<Long, Integer>> newList = gotList();

		Monster monster = Context.getUndercityServer().getMonster(monsterId);
		Scene scene = Context.getSceneServer().getSceneById(currentSceneId);

		List<WorldBossAkVo> orderList = new ArrayList<WorldBossAkVo>();
		List<Object> headNames = new ArrayList<Object>();
		int orderId = 0;
		StringBuilder sb = new StringBuilder();
		for (Entry<Long, Integer> e : newList) {
			orderId++;

			long playerId = e.getKey();
			int akNum = playerAkMap.get(playerId);
			int damNum = playerDaMap.get(playerId);
			WorldBossAkVo akVo = new WorldBossAkVo(playerId, orderId, akNum, damNum);
			orderList.add(akVo);
			if (orderId == 1) {
				lastKillerId = akVo.getPlayerId();
				lastKillerName = akVo.getPlayerName();
			}
			String title = LanguageLib.get("activity.boos.mailtitle", scene.getName());
			String content = LanguageLib.get("activity.boos.mailcontent", akVo.getPlayerName(), scene.getName(), orderId);

			int awardsTypeId = orderId;
			if (orderId >= 4 && orderId <= 6) {
				awardsTypeId = 4;
			} else if (orderId >= 7 && orderId <= 10) {
				awardsTypeId = 5;
			} else if (orderId >= 11 && orderId <= 20) {
				awardsTypeId = 6;
			}

			SysModeAwards sysAwards = SysModeAwards.get(awardsRootId, awardsTypeId);
			if (sysAwards == null) {
				continue;
			}
			List<SubPops> currentPops = new ArrayList<SubPops>();
			for (SubPops ep : sysAwards.getSubPopsList()) {
				if (ep.getRantGoodsIds() == null) {
					currentPops.add(ep);
				} else {
					currentPops.add(ep.copyByRand());
				}
			}
			Context.getMessageServer().sendSysMail(akVo.getPlayerId(), akVo.getPlayerName(), title, content, currentPops);
			if (orderId <= 3) {
				sb.append(akVo.getPlayerName());
				if (orderId < 3 && orderId != newList.size()) {
					sb.append(',');
				}
				headNames.add(new Object[] { akVo.getPlayerId(), akVo.getPlayerName(), damNum, orderId });
			}

			if (orderId >= 20 || orderId == newList.size()) {
				break;
			}

		}
		String lastBlowKillerName = null;
		if (lastBlowKiller > 0) {
			Player lastBlowPlayer = Context.getPlayerServer().getByPlayerId(lastBlowKiller);
			if (lastBlowPlayer != null) {
				lastBlowKillerName = lastBlowPlayer.getPlayerName();
				// String killerMessage =
				// LanguageLib.get("activity.boos.killer",
				// lastBlowPlayer.getPlayerName(), scene.getName(),
				// monster.getName());
				String killerMessage = LanguageLib.get("activity.boos.killer", LangUtil.makeNameLink(lastBlowPlayer), scene.getName(), monster.getName());
				ChatMain.systemMessage(killerMessage);

				String title = LanguageLib.get("activity.boos.lastkilltitle", scene.getName());
				String content = LanguageLib.get("activity.boos.lastkillcontent", lastBlowKillerName, scene.getName());
				List<SubPops> currentPops = new ArrayList<SubPops>();
				SubPops subPops = new SubPops();
				subPops.setAsset(200000);
				currentPops.add(subPops);
				Context.getMessageServer().sendSysMail(lastBlowKiller, lastBlowKillerName, title, content, currentPops);
			}
		}

		if (orderId > 0) {
			String commMessage = LanguageLib.get("activity.boos.killercomm", scene.getName(), sb.toString(), orderId);
			ChatMain.systemMessage(commMessage);
			EventNotice notice = new EventNotice(ConstantsRadio.boss, ConstantsRadio.boss_DeadNotice);
			notice.put("orderNames", headNames);
			notice.put("bossHpMax", bossHpMax);
			if (lastKillerId > 0) {
				notice.put("lastBlowKiller", lastBlowKiller);
				notice.put("lastBlowKillerName", lastBlowKillerName);
			}
			notice.broadcast(playerDaMap.keySet());

		}
		// 这里要做清理工作
		clear(true);

		akList = orderList;
	}

	private void clear(boolean end) {
		playerAkMap.clear();
		playerDaMap.clear();
		playerDeadMap.clear();
		if (end) {
			playerBuffMap.clear();
		}
	}

	public List<WorldBossAkVo> getAkList() {
		return akList;
	}

	public long getLastKillerId() {
		return lastKillerId;
	}

	public String getLastKillerName() {
		return lastKillerName;
	}

	public boolean isCanBattle() {
		return lastRefresh > 0 && TimeProcesser.getUnixTime() < lastRefresh + bossLifeTime;
	}

	public int getLastRefresh() {
		return lastRefresh;
	}

	public int getLastClac() {
		return lastClac;
	}

	public int getPlayerBuff(long playerId) {
		if (playerBuffMap.containsKey(playerId)) {
			return playerBuffMap.get(playerId);
		}
		return 0;
	}

	public void playerBuffSet(long playerId, int v) {
		playerBuffMap.put(playerId, v);
	}

	public int playerDeadGet(long playerId) {
		if (playerDeadMap.containsKey(playerId)) {
			return playerDeadMap.get(playerId);
		}
		return 0;
	}

	public void playerDeadSet(long playerId, int v) {
		if (v == 0) {
			playerDeadMap.remove(playerId);
		} else {
			playerDeadMap.put(playerId, v);
		}

	}

	public static WorldBoos getById(int id) {
		return commData.get(id);
	}

	public static WorldBoos getBySceneId(int sceneId) {
		return sceneData.get(sceneId);
	}

	public static Collection<WorldBoos> getAll() {
		return commData.values();
	}

	public static List<WorldBoos> getAllList() {
		return new ArrayList<WorldBoos>(commData.values());
	}

	public static int getLastDead() {
		return bosslastDead;
	}

	@Override
	public int compareTo(WorldBoos o) {
		if (o.getRefreshTime() < getRefreshTime()) {
			return 1;
		} else {
			return -1;
		}
	}

}
